﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Printing;
using LogLib;

namespace ComLib.ComFun
{
    public enum PrintingQueueStatus : int
    {
        None = -1,
        Ready = 0,
        Printing = 1,
        Error = 2,
    }

    public class PrinterService
    {
        private static string _error;
        public static string ErrorMessage
        {
            get { return _error; }
            set { _error = value; }
        }

        private static EnumeratedPrintQueueTypes[] enumerationFlags = { EnumeratedPrintQueueTypes.Local, EnumeratedPrintQueueTypes.Connections, };

        private static LocalPrintServer _pService;

        private static List<string> listPrinters = new List<string>();
        public static List<string> Printers
        {
            get { return listPrinters; }
        }

        public static bool CreatePrinterService()
        {
            try
            {
                _pService = new LocalPrintServer();
                _pService.Refresh();
                GetPrinters();
                return true;
            }
            catch (Exception ex)
            {
                _error = "打印机服务异常: " + ex.Message;
                Log.WriteException(ex.ToString());
                return false;
            }         
        }

        static PrinterService()
        {
          
        }
      
        private static void GetPrinters()
        {
            listPrinters.Clear();         
            foreach (PrintQueue pq in _pService.GetPrintQueues(enumerationFlags))
            {
                listPrinters.Add(pq.Name);             
            }
        }

        public static bool Exists(string printerName)
        {
            return listPrinters.Contains(printerName);
        }

        public static PrintQueue GetPrinter(string printerName)
        {
            PrintQueueCollection collection = _pService.GetPrintQueues(enumerationFlags);
            return collection.First(r => r.Name == printerName);
        }

        public PrintingQueueStatus CheckPrinterService(string printerName)
        {
            try
            {
                if (_pService == null)
                {
                    CreatePrinterService();
                }
                _pService.Refresh();
                PrintQueue pq = _pService.GetPrintQueue(printerName);
                pq.Refresh();
                if (pq.IsInError)
                {
                    Log.WriteAsync(printerName + " IsInError");
                    return PrintingQueueStatus.Error;
                }
                if (pq.IsPrinting)
                {
                    Log.WriteAsync(printerName + " IsPrinting");
                    return PrintingQueueStatus.Printing;
                }          
                return PrintingQueueStatus.Ready;
            }
            catch (Exception ex)
            {
                Log.WriteException(ex.ToString());
                return PrintingQueueStatus.Error;
            }
        }

        public static bool CheckPrinterIsReady(string printerName)
        {
            try
            {
                string strLog = "";
                _pService.Refresh();
                PrintQueue pq = _pService.GetPrintQueue(printerName);
                pq.Refresh();
                if (pq.IsInError)
                {
                    strLog = string.Format("{0} is in error.", printerName);
                    Log.WriteAsync(strLog);
                    return false;
                }
                if (pq.IsPrinting)
                {
                    strLog = string.Format("{0} is in printing.", printerName);
                    Log.WriteAsync(strLog);
                    return false;                 
                }
                PrintJobInfoCollection allPrintJobs = pq.GetPrintJobInfoCollection();               
                if (allPrintJobs.Count() == 0)
                {
                    return true;
                }

                PrintSystemJobInfo info = allPrintJobs.ElementAt(0);
                strLog = string.Format("{0} is {1}.", info.JobStatus);
                Log.WriteAsync(strLog);
                return false;    
            }
            catch (Exception ex)
            {
                Log.WriteException(ex.ToString());
                return false;                 
            }
        }

        public static PrintingQueueStatus CheckPrintingQueueService(string printerName)
        {
            try
            {
                LocalPrintServer pServer = new LocalPrintServer();
                pServer.Refresh();
                PrintQueue pq = pServer.GetPrintQueue(printerName);
                pq.Refresh();
                if (pq.IsInError)
                {
                    Log.WriteAsync("pq.IsInError");
                    return PrintingQueueStatus.Error;
                }
                if (pq.IsPrinting)
                {
                    Log.WriteAsync("pq.IsPrinting");
                    return PrintingQueueStatus.Printing;
                }
                PrintJobInfoCollection allPrintJobs = pq.GetPrintJobInfoCollection();
                if (allPrintJobs.Count() == 0)
                {
                    return PrintingQueueStatus.Ready;
                }
                PrintSystemJobInfo info = allPrintJobs.ElementAt(0);
                if (info.IsInError || info.IsPrinting)
                {
                    Log.WriteAsync("info.IsInError || info.IsPrinting");
                    return PrintingQueueStatus.Error;
                }
                return PrintingQueueStatus.Ready;
            }
            catch (Exception ex)
            {
                Log.WriteException(ex.ToString());
                return PrintingQueueStatus.Error;
            }
        }

        public static void ClearPrintQueue(string printerName)
        {
            try
            {
                PrintQueue pq = _pService.GetPrintQueue(printerName);
                pq.Refresh();
                PrintJobInfoCollection allPrintJobs = pq.GetPrintJobInfoCollection();
                if (allPrintJobs.Count() == 0)
                {
                    return;
                }
                string strLog = string.Format("开始清理打印机{0}的{1}个任务:", printerName, allPrintJobs.Count());
                Log.WriteAsync(strLog);
                foreach (PrintSystemJobInfo printJob in allPrintJobs)
                {
                    printJob.Cancel();
                    strLog = string.Format("打印任务{0}:{1}已取消.", printJob.JobIdentifier, printJob.JobName);
                    Log.WriteAsync(strLog);
                }
                Log.WriteAsync(printerName + "的打印任务已全部取消");
            }
            catch(Exception ex)
            {
                Log.WriteException(ex.ToString());
            }
        }
        //public bool CancelPrintJob(int printJobID)
        //{
        //    // Variable declarations.            
        //    bool isActionPerformed = false;
        //    string searchQuery;
        //    String jobName;
        //    char[] splitArr;
        //    int prntJobID;
        //    ManagementObjectSearcher searchPrintJobs;
        //    ManagementObjectCollection prntJobCollection;
        //    try
        //    {
        //        // Query to get all the queued printer jobs.                
        //        searchQuery = "SELECT * FROM Win32_PrintJob";
        //        // Create an object using the above query.                
        //        searchPrintJobs = new ManagementObjectSearcher(searchQuery);
        //        // Fire the query to get the collection of the printer jobs.                
        //        prntJobCollection = searchPrintJobs.Get();
        //        // Look for the job you want to delete/cancel.                
        //        foreach (ManagementObject prntJob in prntJobCollection)
        //        {
        //            jobName = prntJob.Properties["Name"].Value.ToString();
        //            // Job name would be of the format [Printer name], [Job ID]                    
        //            splitArr = new char[1];
        //            splitArr[0] = Convert.ToChar(",");
        //            // Get the job ID.                    
        //            prntJobID = Convert.ToInt32(jobName.Split(splitArr)[1]);
        //            // If the Job Id equals the input job Id, then cancel the job.                    
        //            if (prntJobID == printJobID)
        //            {
        //                // Performs a action similar to the cancel                        
        //                // operation of windows print console                        
        //                prntJob.Delete();
        //                isActionPerformed = true;
        //                break;
        //            }
        //        }
        //        return isActionPerformed;
        //    }
        //    catch (Exception ex)
        //    {
        //        // Log the exception.                
        //        return false;
        //    }
        //}
    }
}
